#include "adr_component.h"

#include <iostream>
#include "adr_version.h"
#include <thread>
#include <sys/prctl.h>

#include "dds_data_receiver.h"
#include "public_define.h"
#include "eventcommand.h"
#include "collect_config.h"
#include "eventloop.h"
#include "adr_trigger.h"
#include "data_cache.h"
#include "dds_topic_header.h"
#include "data_structure.h"
#include "antianaphylaxis_queue.h"
#include "adr_fileupload.pb.h"
#include "data_build.h"
#include "state_machine.pb.h"
#include "vcu.pb.h"
#include "config_signal_parse.h"
#include "adr_trigger.pb.h"
#include "soaCarFileUpload.h"
#include "Common.pb.h"
#include "bushuset.pb.h"

#include "soaAndrEnvir.h"
#include "soaC2SignalToEdc.h"
#include "soaQueryFilePathInfo.h"
#include "soaVideoRecordServer.h"
#include "soaEnginerringModel.h"
#include "soaGetFileDirRpc.h"
#include "soaUploadFileServer.h"
#include "filemanagercommand.h"
#include "special_trigger.h"
#include "crecord.h"
#include "event_reupload.h"
#include "Basc_DCFileUpload.pb.h"
#include "file_uploader.h"

#include "calibration_file.h"
#include "fileReupload.h"
#include "map_collect.h"
#include "manager_file.h"
#include "bus_veh_info.pb.h"
#include "desensitize.h"

// #include "sys/stat.h"
#include <dirent.h>

#include "interface/capilot_module_interface.pb.h"
#include "eol.pb.h"
#include "hb_mem_mgr.h"



REGISTER_COMPONENT("adr", adr_component);

using namespace DcAdr;

#define RTLD_LAZY 0x00001
#define LIBTLS_PATH "/svp/lib/libdsvpkcs.so"
static void *g_pdlhandler_adr = NULL;
static uint8_t (*g_Is_Get_PriKey_adr)(char *, uint32_t *, char *) = NULL;

int global_data::desensitizeSdkInitCount = 0;

struct CombufInfo
{
    hb_mem_common_buf_t com_buf;
    uint64_t last_time;
};

std::mutex mutex_;
std::map<int32_t, CombufInfo> sharedid_combuf_map_;

void parseiaccOdometer(const ProtoData &pbData)
{
    string &topic = *pbData.topic.get();
    string &data = *pbData.data.get();

    // state_switch-Sts.FromSTS
    Sts::FromSTS tmp;
    if (!tmp.ParsePartialFromArray(data.data(), data.size()))
    {
        Log_Info("parseiaccOdometer parse proto data failed ,topic: {}", topic);
        return;
    }

    global_data::g_extEvent.iaccOdometer = tmp.pd_sts_mng().pd_iacc_odometer();
    global_data::g_extEvent.accOdometer = tmp.pd_sts_mng().pd_acc_odometer();  
    global_data::g_extEvent.ndaOdometer = tmp.pd_sts_mng().pd_nda_odometer();  
}


void parsetotalOdometer(const ProtoData &pbData)
{
    string &topic = *pbData.topic.get();
    string &data = *pbData.data.get();

    // sab-VcuProto.Vcu~vcu_engine~vcu_total_milg
    VcuProto::Vcu tmp;
    if (!tmp.ParsePartialFromArray(data.data(), data.size()))
    {
        Log_Info("parsetotalOdometer parse proto data failed ,topic: {}", topic);
        return;
    }

    global_data::g_extEvent.totalOdometer = tmp.vcu_engine().vcu_total_milg();
}

void parseSabBushuset(const ProtoData &pbData)
{
    string &topic = *pbData.topic.get();
    string &data = *pbData.data.get();

    // sab-VcuProto.Vcu~vcu_engine~vcu_total_milg
    BushusetProto::Bushuset tmp;
    if (!tmp.ParsePartialFromArray(data.data(), data.size()))
    {
        Log_Info("parseSabBushuset parse proto data failed ,topic: {}", topic);
        return;
    }

    static uint32_t commit = 0;
    uint32_t nowCom = tmp.hu_ads_fun_set().usr_act_commit_feed_back();
    if (commit == 0x00 && nowCom == 0x01)
    {
        ManagerFile::getInstance().SendBA692Info();
    }
    commit = nowCom;    
}

//add by gd
void getVinCode(const ProtoData &pbData)
{
    if(!global_data::g_car_vin.empty())
        return;
    string &topic = *pbData.topic.get();
    string &data = *pbData.data.get();
    Eol::VinConfig tmp;
    if (!tmp.ParsePartialFromArray(data.data(), data.size()))
    {
        Log_Info("BusVehInfoProto parse proto data failed ,topic: {}", topic);
        return;
    }
    std::string vin=tmp.vin_data();
    if(vin.find("LS")==0)
    {
        global_data::g_car_vin=vin;
    }
    Log_Info("g_car_vin:{}",global_data::g_car_vin);
    return;
}

void parseDiRuanTopic(const ProtoData &pbData)
{
    string &topic = *pbData.topic.get();
    string &data = *pbData.data.get();

    Eol::SystemConfig tmp;
    if (!tmp.ParsePartialFromArray(data.data(), data.size()))
    {
        Log_Info("parseDiRuanTopic parse proto data failed ,topic: {}", topic);
        return;
    }

    global_data::g_C2_bigVersion = tmp.c2_software_version();

    Json::Value root;
    root["c2_software_version"] = tmp.c2_software_version(); 
    root["c2_hardware_version"] = tmp.c2_hardware_version(); 
    root["soc_software_version"] = tmp.soc_software_version(); 
    root["mcu_software_version"] = tmp.mcu_software_version(); 
    root["hardware_part_number"] = tmp.hardware_part_number(); 
    root["serial_number"]        = tmp.serial_number(); 
    root["app_fingerprint_info"] = tmp.app_fingerprint_info(); 
    
    Json::FastWriter writer;
    std::string writeStr = writer.write(root);

    //Log_Info("parseDiRuanTopic; writeStr: {}", writeStr);

    CRecord::AddDiruan(writeStr);
}

void parseFileUploadData(const ProtoData &pbData)
{
    string &topic = *pbData.topic.get();
    string &data = *pbData.data.get();

    // TODO file upload
    AdrTrigger::FileUpload upload;
    if (!upload.ParsePartialFromArray(data.data(), data.size()))
    {
        Log_ERROR("Fileupload parse proto data failed ,topic: {}", topic);
        return;
    }
    Log_Info("Fileupload parse proto data success ,topic: {}", topic);

    Soa::PB_DC_FileList_Struct soaFileList;

    Log_Info("Receive file upload request: {}  event id: {}  file count: {}", topic, upload.event_id(), upload.file_list_size());

    for (int i = 0; i < upload.file_list_size(); ++i)
    {
        auto &file = upload.file_list(i);
        if (file.file_path().empty())
        {
            Log_ERROR("Receive file upload file path empty");
            return;
        }
        if (file.file_name().empty())
        {
            Log_ERROR("Receive file upload file name empty");
            return;
        }

        Soa::PB_DC_FileListStr *fileListStr = soaFileList.add_seq();
        fileListStr->set_filename(file.file_name());
        fileListStr->set_filepath(file.file_path());
        fileListStr->set_filetype(file.file_type());
        fileListStr->set_filesize(file.file_size());

        Log_Info("Receive file upload file name: {}  file path: {}", file.file_name(), file.file_path());
    }

    DataBuild::DataCollectUpload_send(soaFileList, upload.event_id());
}

void parseStatedData(const ProtoData &pbData)
{
    string &topic = *pbData.topic.get();
    string &data = *pbData.data.get();

    Sts::DrivingModeReq tmp;
    if (tmp.ParsePartialFromArray(data.data(), data.size()))
    {
        uint32_t status = tmp.adc_top_mode();
        uint32_t work_status = tmp.adc_work_state();
        if (global_data::g_adc_status != status)
        {
            Log_Info("adc_topic_mode change, old: {}, new: {} ", global_data::g_adc_status, status);
            global_data::g_adc_status = status;
        }
        if (global_data::g_work_status != work_status)//如果work_status发生跳变，更新work_status
        {
            Log_Info("g_work_status change, old: {}, new: {} ", global_data::g_work_status, work_status);
            global_data::g_work_status = work_status;
        }
    }
    else
    {
        Log_ERROR("parse proto data failed ,topic: {}", topic);
    }
}

//标定文件上云
void parseBiaoDing(const ProtoData &pbData)
{
    string &topic = *pbData.topic.get();
    (void)topic;
    string &data = *pbData.data.get();

    AdrTrigger::Trigger tmp;
    if (!tmp.ParsePartialFromArray(data.data(), data.size()))
    {
        return;
    }
    string eventId = tmp.event_id();
    // 事件id为FC011
    if (eventId == "FC011")
    {
        // 删除目标目录的标定文件
        CalibrationFile::deleteCalibrationFile();
        // 读取标定文件
        uint8_t ret = SoaEnginerringModel::getInstance().getCalibrationFile();
        // 事件文件上云
        if (ret)
        {
            SoaEnginerringModel::getInstance().calibrationFileUpload();
            Log_Info("zjs_tmp_dianjian[adr_component][onObjectCallback] Calibration File zip SUCCESS");
        }
        else
        {
            Log_Info("zjs_tmp_dianjian[adr_component][onObjectCallback] Calibration File zip ERROR");
        }
    }
}

// trigger拦截，GPS经纬度赋值给全局变量
void parseGpsData(const ProtoData &pbData)
{
    string &topic = *pbData.topic.get();
    string &data = *pbData.data.get();

    AdrTrigger::GpsData gpsData;
    if (gpsData.ParsePartialFromArray(data.data(), data.size()))
    {
        global_data::g_car_location_lng = gpsData.lng();
        global_data::g_car_location_lat = gpsData.lat();
        // Log_Info("g_car_location_lng: {}, g_car_location_lat: {} ", global_data::g_car_location_lng, global_data::g_car_location_lat);
    }
    else
    {
        Log_ERROR("GpsData parse proto data failed , topic: {}", topic);
    }
}

// 环境切换,如果环境是预生产，data.size是1，反序列化会失败，反序列化参数用特殊处理的pbData._length
void parseAndroidEnv(const ProtoData &pbData)
{
    string &topic = *pbData.topic.get();
    (void)topic;
    string &data = *pbData.data.get();

    AdrTrigger::AndroidEnvironment tmp;
    if (!tmp.ParsePartialFromArray(data.data(), pbData._length))
    {
        Log_Info("[adr_component][onObjectCallback] ParsePartialFromArray AndroidEnvironment error!");
        return;
    }
    const uint32_t env = tmp.environment();
    SoaAndrEnvir::getInstance().Receive_AndroidEnvironment_Notify(env);
}

// 地图map采集
void parseMapCollect(const ProtoData &pbData)
{
    string &topic = *pbData.topic.get();
    string &data = *pbData.data.get();

    //10ms一帧 zjs_todo;放到单独线程里处理？
    {
        static int aa = 0;
        aa++;
        if (aa % 50 == 0)//10ms * 50 = 500ms进来判断一次
        {
            aa = 0;
            // Log_Info("zjs_tmp_0617; recv InsData");
            MapCollect::getInstance().mapEventhappen(topic, data, pbData.time);
        }        
    }
}

// 速度获取
void parseSpeed(const ProtoData &pbData)
{
    string &topic = *pbData.topic.get();
    (void)topic;
    string &data = *pbData.data.get();

    MapCollect::getInstance().SetSpeed(data);
}

void Rec_Ntf_UploadFile_Cmd(const ProtoData &pbData)
{
    Log_Info("[SoaUploadFileServer] [Ntf_UploadFile]");
    string &topic = *pbData.topic.get();
    string &data = *pbData.data.get();
    Soa::PB_Basc_DCFileUpload_Ntf_UploadFile_In uploadFile;
    if (!uploadFile.ParsePartialFromArray(data.data(),pbData._length))
    {
        Log_ERROR("[SoaUploadFileServer] [Ntf_UploadFile] parse proto data failed , topic: {}", topic);
    }

    std::string taskId = uploadFile.taskid();
    std::string eventCode = uploadFile.eventcode();
    std::string files = uploadFile.files();
    //FileUploader tmp;
    FileUploader::getInstance().uploadFile(taskId, files, eventCode);

    return;
}

typedef void (*funcp22)(const ProtoData &pbData);
std::unordered_map<string, funcp22> specTopiDeal =   //modify by gd 2025/2/11
{
    {"camera_diag-Eol.SystemConfig",parseDiRuanTopic},
    {"car_scheduler-AdrTrigger.FileUpload",parseFileUploadData},//BA513
    {"state_switch-Sts.DrivingModeReq",parseStatedData},
    {"ad_algo_ego-AdrTrigger.Trigger",parseBiaoDing},
    {"sab-AdrTrigger.GpsData",parseGpsData},
    {"sab-AdrTrigger.AndroidEnvironment",parseAndroidEnv},
    {"ad_algo_ins-localization.InsData-Du",parseMapCollect},
    {"sab-BusespProto.BusEsp",parseSpeed},

    {"state_switch-Sts.FromSTS",parseiaccOdometer},
    {"sab-VcuProto.Vcu",parsetotalOdometer},

    {"sab-BushusetProto.Bushuset",parseSabBushuset},
    {"camera_diag-Eol.VinConfig",getVinCode}
	//{"internet_manager-Soa.PB_Basc_DCFileUpload_Ntf_UploadFile_In",Rec_Ntf_UploadFile_Cmd},
    
};



adr_component::adr_component()
    : CaNode("adr")
{
    // SoaAndrEnvir::getInstance().setRequestHandle(this);
    SoaC2SignalToEdc::getInstance().setPublishHandle(this);
    AntianaphylaxisQueue::getInstance().setPublishHandle(this);
}

adr_component::~adr_component()
{
    for (auto pointer: vPointers)
    {
        delete pointer;
    }
    vPointers.clear();
}

int adr_component::dlopen_getCer()
{
    if (g_pdlhandler_adr == NULL)
    {
        g_pdlhandler_adr = dlopen(LIBTLS_PATH, RTLD_LAZY);

        if (g_pdlhandler_adr == NULL)
        {
            Log_Info("dlopen:{} failed", LIBTLS_PATH);
            return -1;
        }
        else
        {
            g_Is_Get_PriKey_adr = (uint8_t(*)(char *, uint32_t *, char *))dlsym(g_pdlhandler_adr, "get_ipu04_private_key");
            if (g_Is_Get_PriKey_adr == NULL)
            {
                Log_Info("dlopen get interface failed");
                return -1;
            }
        }
    }

    return 0;
}

void adr_component::encapCerJudge()
{
    // if (dlopen_getCer())//获取get解密接口不成功
    // {
    //     return;
    // }

    //bool encapCerOk = false;
    const string folderPath = "/image_conf";
    DIR *dir = opendir(folderPath.c_str());
    if (NULL == dir)
    {
        Log_Info("目录文件:{}  打开失败!!!", folderPath);
        return;
    }

    struct dirent *dir_info;
    string onefile;
    std::string absPath = "";
    while ((dir_info = readdir(dir))!=nullptr)
    {
        onefile = dir_info->d_name;
        
        Log_Info("image files: onefile: {}", onefile);

        if ((onefile.find(".cer") != std::string::npos))//有灌装的证书
        {
            //是否能找到对应的key
            string encodeKey = onefile.substr(0, onefile.find_last_of(".")) + ".key";
            string encodeKeyPath = folderPath + "/" +  encodeKey;
            Log_Info("image encodeKeyPath:{}", encodeKeyPath);
            if (!CommonOprSystem::isPathExist(encodeKeyPath))
            {
                continue;
            }
            
            absPath = folderPath + "/" + dir_info->d_name;
            string cerContent;
            string keyContent;
            CommonOprSystem::readFileAllOnce(absPath, cerContent);
            CommonOprSystem::readFileAllOnce(encodeKeyPath, keyContent);
            Log_Info("zjs_tmp_0416; 22 onefile: {} cerContent_size():{}", absPath, cerContent.size());

            Log_Info("zjs_tmp_0416; 33 cerContent: {}", cerContent);
            Log_Info("keyfile path:{},key size:{}",encodeKeyPath,keyContent.size());

            if (!cerContent.empty())//证书有内容
            {
                global_data::g_client_keyBuff = keyContent;
                global_data::g_http_ca_path = "/image_conf/";
                global_data::g_tuid_path = "/image_conf/TUID.txt";
                global_data::g_client_cert = onefile;
                global_data::g_client_key = encodeKey;
                Log_Info("[adr] use_cer; guanzhuang");
                //C3B 调试联网阶段使用明码key，暂时不用解密接口
                #if 0
                //解密证书
                char key[65535] = {0};//zjs_todo 太大了改小
                uint32_t len = 0;

                if (g_Is_Get_PriKey_adr(key, &len, const_cast<char*>(encodeKey.c_str())) != 0)
                {
                    Log_Info("get_ipu04_private_key failed");
                    break;
                }
                Log_Info("jiemi_key key_len:{}", len);

                /*****************/
                global_data::g_client_keyBuff =  key;
                Log_Info("zjs_tmp_miwen;jiemi_key key_len:{}", global_data::g_client_keyBuff.size());

                global_data::g_http_ca_path = "/image_conf/";
                global_data::g_tuid_path = "/image_conf/TUID.txt";
                global_data::g_client_cert = onefile;
                Log_Info("[adr] use_cer; guanzhuang");
                #endif
            }

            break;
        }
    }

    closedir(dir);
}

void adr_component::cerJudge()
{
    string oldCer = global_data::g_http_ca_path + global_data::g_client_cert;
    string oldKey = global_data::g_http_ca_path + global_data::g_client_key;
    //以前的从edc拉取证书方式存在，用以前的。否则用灌装的证书
    if (0 == access(oldCer.c_str(), F_OK))
    {
        Log_Info("have; oldCer: {}", oldCer);
        CommonOprSystem::readFileAllOnce(oldKey, global_data::g_client_keyBuff);
    }
    else
    {
        encapCerJudge();
    }

    Log_Info("[adr] use_cer; g_http_ca_path:{} g_tuid_path:{} g_client_cert:{} g_client_key:{} g_client_keyBuff_size():{}",
            global_data::g_http_ca_path, global_data::g_tuid_path, global_data::g_client_cert, global_data::g_client_key, global_data::g_client_keyBuff.size());

    return;
}

void adr_component::timeOut_sendDiagnosis()
{
    static uint32_t heart = 0;
    global_data::g_adrDiagnosisSts.set_time_stamp(Util::getMsTime() * 1000);
    global_data::g_adrDiagnosisSts.set_heartbeat(heart);
    // if (!IsCerFileExist())
    // {
    //     ModifyDiagnosisSts(1);
    // }
    //string adrStatus;
    //global_data::g_adrDiagnosisSts.SerializePartialToString(&adrStatus);
    //publish(adrStatus, "adr-AdrInterface.AdrDiagnosis");
    publish(global_data::g_adrDiagnosisSts, "adr-AdrInterface.AdrDiagnosis");
    //Log_Info("send diagnosis:{}", global_data::g_adrDiagnosisSts.DebugString());

    global_data::g_adrDiaagnosisSts.set_diagnosis_code(0);
    global_data::g_adrDiagnosisSts.set_diagnosis_info("");
    heart++;
    if (heart == 256)
    {
        heart = 0;
    }
}

void adr_component::adrInit()
{
    // 1. 设置全局工作状态为2（可能表示"初始化中"或"运行中"，具体含义取决于全局状态定义）
    //global_data::g_work_status =2;
    
    // 2. 调用Linux系统调用prctl，将当前线程名称设置为"dc_main"（便于调试时识别线程）
    prctl(PR_SET_NAME, "dc_main");
    
    // 3. 输出日志：记录adr进程启动，版本标识3344及正式版本号
    Log_Info("[adr] process run,version 3344: {}", adr_VERSION);
    
    // 4. 初始化事件循环框架（可能用于处理异步事件、定时器等）
    EventLoop::init();

    // 5. 检查全局数据文件存储路径是否存在
    int ret = access(global_data::g_data_path.c_str(), F_OK);
    // 6. 若路径不存在，则创建该目录，权限为S_IRWXU（所有者可读写执行）
    if (0 != ret)
    {
        int retCI = mkdir(global_data::g_data_path.c_str(), S_IRWXU);
        (void)retCI; // 忽略返回值（避免未使用变量警告）
    }

    // 7. 检查证书文件是否存在
    ret = access("/app/ca_adas/csmap/config/ca.crt", F_OK);
    // 8. 若存在，则复制到"/ds/ca_adas/"目录（可能用于证书统一管理）
    if (0 == ret)
    {
        std::string cmd="cp /app/ca_adas/csmap/config/ca.crt /ds/ca_adas/";
        int retCI=std::system(cmd.c_str()); // 执行shell命令
        (void)retCI; // 忽略返回值
    }

    // 9. 检查老版本解密key文件"/image_conf/test_key.key"是否存在
    ret = access("/image_conf/test_key.key", F_OK);
    // 10. 若存在则删除（注释说明：信息安全要求删除旧版解密key）
    if (0 == ret)
    {
        int retCI = remove("/image_conf/test_key.key");
        Log_Info("have jiemiKey;delet file ret:{}", retCI); // 记录删除结果
    }
    
    // 11. 检查根证书文件"/image_conf/rootca.cer"是否存在
    ret = access("/image_conf/rootca.cer", F_OK);
    // 12. 若存在则删除（注释说明：避免影响解密key，移除旧位置的根证书）
    if (0 == ret)
    {
        int retCI = remove("/image_conf/rootca.cer");
        Log_Info("have /image_conf/rootca.cer ;delet file ret:{}", retCI); // 记录删除结果
    }
 
    // 13. 拼接根证书路径（全局配置的证书目录+根证书文件名）
    string imagRootCa = global_data::g_SdaCaFilePath + global_data::g_rootCaCertPem;
    // 14. 获取根证书文件大小（单位可能为字节）
    uint64_t fileSize = CommonOprSystem::getFileSizeDigit(imagRootCa);
    // 15. 若文件大小小于1024字节（1KB），判定为无效文件并删除
    if (fileSize < 1024)
    {
        int retCI = remove(imagRootCa.c_str());
        Log_Info("imagRootCa too small delet; ret:{}", retCI); // 记录删除结果
    }
    
    // 16. 初始化RPC相关话题（可能包含RPC服务注册、话题绑定等）
    rpcTopicInit();

    // 17. 绑定RPC请求处理函数：处理"文件上传通知"类型的RPC请求
    BindRequest<Soa::PB_Basc_DCFileUpload_Ntf_UploadFile_In,
                Soa::PB_Basc_DCFileUpload_Ntf_UploadFile_Out>([&]
        (const Soa::PB_Basc_DCFileUpload_Ntf_UploadFile_In &request,
        Soa::PB_Basc_DCFileUpload_Ntf_UploadFile_Out *reply){
            // 18. 日志记录收到的请求数据（调试用）
            Log_Info("[SoaUploadFileServer] [Ntf_UploadFile] recdata: {}", request.DebugString());
            // 19. 解析请求参数：任务ID、事件编码、文件列表
            std::string taskId = request.taskid();
            std::string eventCode = request.eventcode();
            std::string files = request.files();
            // 20. 调用FileUploader单例上传文件
            FileUploader::getInstance().uploadFile(taskId, files, eventCode);
            // 21. 设置回复状态码为2001（可能表示"处理成功"）
            reply->mutable_return_()->set_code(2001);
        },
        PB_BASC_DCFILEUPLOAD_NTF_UPLOADFILE_IN); // 绑定的RPC话题标识

    // 22. 绑定RPC请求处理函数：处理"查询文件路径信息"类型的RPC请求
    BindRequest<Soa::PB_QueryFilePathInfo_Get_QueryFilePathInfo_In,
                Soa::PB_QueryFilePathInfo_Get_QueryFilePathInfo_Out>([&]
        (const Soa::PB_QueryFilePathInfo_Get_QueryFilePathInfo_In &request,
        Soa::PB_QueryFilePathInfo_Get_QueryFilePathInfo_Out *reply){
            // 23. 日志记录收到的请求数据（调试用）
            Log_Info("[SoaQueryFilePathInfo] [Get_QueryFilePathInfo] recdata:{}",request.DebugString());

            // 24. 解析请求参数：控制器编码、搜索路径
            std::string controllerCode = request.controllercode();
            std::string searchPath = request.searchpath();
            // 25. 临时变量：存储文件路径列表和消息
            string tempfilePathList = "";
            string tempmsg = "";

            // 26. 若请求的控制器编码与本地编码一致（表示是TBOX设备），则处理查询
            if (!controllerCode.compare(global_data::g_controler_code))
            {
                // 27. 调用SoaQueryFilePathInfo单例获取文件路径信息
                SoaQueryFilePathInfo::getInstance().getPathFileInfo(searchPath, tempfilePathList, tempmsg);
            }
            else
            {
                // 28. 若控制器编码不匹配，休眠5秒后返回错误信息
                std::this_thread::sleep_for(std::chrono::milliseconds(5000));
                tempmsg = "error,controllerCode is " + controllerCode + "not " + global_data::g_controler_code;
                tempfilePathList = tempmsg;
            }
            // 29. 设置回复状态码、文件路径列表和消息
            reply->mutable_return_()->set_code(2001);
            reply->mutable_return_()->set_filepathlist(tempfilePathList);
            reply->mutable_return_()->set_msg(tempmsg);

            Log_Info("[QueryFilePathInfo] SoaQueryFilePathInfo succ!"); // 记录处理成功
        },
        PB_QUERYFILEPATHINFO_GET_QUERYFILEPATHINFO_IN); // 绑定的RPC话题标识

    // 30. 遍历全局配置的RPC话题列表（g_topics_rpc）
    for (const std::string &topicRpcStr : global_data::g_topics_rpc)
    {
        Log_Info("[adr] Init RPC topic: {}", topicRpcStr); // 记录初始化的RPC话题
        // 31. 创建Capilot数据接收器实例（用于处理RPC数据）
        CapilotDataReceiver *dataRpcRec = new CapilotDataReceiver();
        // 32. 初始化RPC接收器：绑定当前组件、话题、回调函数onObjectRpcCallback
        dataRpcRec->initRpc(this, topicRpcStr, std::bind(&adr_component::onObjectRpcCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
        // 33. 保存接收器指针到列表（便于后续管理）
        vPointers.push_back(dataRpcRec);
    }
    
    // 激光模块的一个逻辑判断
    if (hb_mem_module_open() != 0)
    {
        Log_Info("hb_mem_module_open err failed"); // 打开失败日志
    }
    Log_Info("[adr] init hb_men success ..."); // 打开成功日志

    // 35. 绑定定时器回调：定时执行timeOut_sendDiagnosis（间隔从配置获取）
    bindTimerCallback(std::bind(&adr_component::timeOut_sendDiagnosis, this), getInt("interval"));
    // 36. 绑定定时器回调：每150毫秒执行一次getDataFromCapilot（从Capilot拉取数据）
    bindTimerCallback(std::bind(&adr_component::getDataFromCapilot, this), 150);
    
    // 37. 初始化数据缓存模块，设置发布句柄为当前组件（用于数据发布）
    DataCache::getInstance().setPublishHandle(this);

    // 38. 执行证书判断（验证证书有效性等）
    cerJudge();

    // 39. 主动获取安卓环境信息（如系统版本、配置等）
    selfGetAndrEnvir();

    // 40. 初始化配置收集器（拉取并加载系统配置）
    CollectConfig::getInstance().init();
    Log_Info("[adr] get config success 0802..."); // 记录配置获取成功（0802可能是版本标识）

    // 41. 检查文件重传路径（g_file_reupload_path）是否存在
    int ret1 = access(global_data::g_file_reupload_path.c_str(), F_OK);
    // 42. 若不存在，创建空文件（用于记录需要重传的文件）
    if (0 != ret1)
    {
        string tmpNull;
        CommonOprSystem::writeStringBuffToFile(global_data::g_file_reupload_path, tmpNull);
    }

    // 43. 获取节点接口信息（可能是组件间通信的接口定义）
    capilot::interface::InterfaceReply reply = GetNodeInterface();
    // 44. 设置CRecord的版本信息（可能用于数据记录的版本标识）
    CRecord::SetVersion(reply);

    // 45. 上电时检测并补传事件文件（从存储中读取未上传的事件并发送）
    EventReupload::getInstance().readEvtAndSend();

    // 46. 初始化主要组件AdrTrigger（事件触发判断逻辑）
    DcAdr::AdrTrigger::getInstance();

    // 47. 初始化地图围栏配置解析器（解析地图围栏数据）
    MapCollect::getInstance();

    // 48. 初始化文件管理器：设置配置文件路径
    FileManagerCommand::getInstance()->setFileManagerCfgPath(global_data::g_file_manager_conf);

    // 49. 从配置中获取需要订阅的话题列表，赋值给全局变量g_topics
    global_data::g_topics = getStringVector("sub_topic");
    // 50. 复制订阅话题列表到无停车场场景的话题列表
    global_data::g_no_parking_topics=global_data::g_topics;

    // 51. 初始化标定文件（加载传感器标定数据等）
    calibFileInit();

    // 52. 初始化视频相关话题（订阅/发布视频数据）
    vedioTopicInit();
    // 53. 初始化中间件相关话题（处理中间层数据）
    midTopicInit();
    // 54. 初始化图片相关话题（订阅/发布图片数据）
    pictureTopicInit();
    // 55. 初始化停车场数据采集话题（传入配置路径）
    parkCollectTopicInit(global_data::g_parkTopc_conf);

    // 56. 输出日志：记录各类型话题的数量（调试用）
    Log_Info("need collect topic;size: g_topics: {}  g_topics_mid: {}  g_topics_vedio: {}  g_topics_pic: {}", global_data::g_topics.size(), global_data::g_topics_mid.size(), global_data::g_topics_vedio.size(), global_data::g_topics_pic.size());

    // 57. 条件编译（#if 0表示不启用）：初始化普通话题的代码
    #if 0
    for (const std::string &topicStr : global_data::g_topics) 
    {
        Log_Info("[adr] Init topic: {}", topicStr);
        CapilotDataReceiver *dataRec = new CapilotDataReceiver();
        // 绑定话题与回调函数onObjectCallback
        dataRec->init(this, topicStr, std::bind(&adr_component::onObjectCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
        vPointers.push_back(dataRec);
    }
    #endif
    
    // 58. 输出日志：初始化线程成功
    Log_Info("[DataCollect] init threads success...");
    
    // 59. 获取主线程的事件循环实例
    auto loop = EventLoop::getInstance(ThreadType::E_InMainThread);
    // 60. 启动事件循环（进入事件处理循环，处理定时器、消息等）
    loop->exec();
    
    // 61. 事件循环退出后，输出主线程退出日志
    Log_Info("[DataCollect] main thread quit...");
}

void adr_component::vedioTopicInit()
{
    global_data::g_topics_vedio.clear();
    global_data::g_topics_vedio.push_back(ENCODE_SRV_H265_CAM0);
    global_data::g_topics_vedio.push_back(ENCODE_SRV_H265_CAM1);
    global_data::g_topics_vedio.push_back(ENCODE_SRV_H265_CAM2);
    global_data::g_topics_vedio.push_back(ENCODE_SRV_H265_CAM3);
    global_data::g_topics_vedio.push_back(ENCODE_SRV_H265_CAM4);
    global_data::g_topics_vedio.push_back(ENCODE_SRV_H265_CAM5);
    global_data::g_topics_vedio.push_back(ENCODE_SRV_H265_CAM6);
    global_data::g_topics_vedio.push_back(ENCODE_SRV_H265_CAM7);
    global_data::g_topics_vedio.push_back(ENCODE_SRV_H265_CAM8);
    global_data::g_topics_vedio.push_back(ENCODE_SRV_H265_CAM9);
    global_data::g_topics_vedio.push_back(ENCODE_SRV_H265_CAM10);
}

void adr_component::parkCollectTopicInit(std::string path)
{
    ifstream infile(path);
    if (infile)
    {
        string strline = "";
        while (getline(infile, strline))
        {
            if (!strline.empty())
            {
               global_data::g_parking_topics.push_back(strline);
               Log_Info("g_parkTopc_conf :{}",strline);
            }
            
            strline = "";
        }

        infile.close();
    }
    else
    {
        Log_Info("***Not find g_parkTopc_conf:{} !!!", path);
    }
    //Log_Info("g_parkTopc_conf size:{}",global_data::g_allCollect_topics.size());
    return;
}
void adr_component::midTopicInit()
{
    global_data::g_topics_mid = global_data::g_topics;

    set<string> tmp_video = {
        ENCODE_SRV_H265_CAM0,
        ENCODE_SRV_H265_CAM1,
        ENCODE_SRV_H265_CAM2,
        ENCODE_SRV_H265_CAM3,
        ENCODE_SRV_H265_CAM4,
        ENCODE_SRV_H265_CAM5,
        ENCODE_SRV_H265_CAM6,
        ENCODE_SRV_H265_CAM7,
        ENCODE_SRV_H265_CAM8,
        ENCODE_SRV_H265_CAM9,
        ENCODE_SRV_H265_CAM10,
    };

    set<string> tmp_picture = {
        "encode_srv-EncodeSrv.EncodeJpeg-CAM0",
        "encode_srv-EncodeSrv.EncodeJpeg-CAM1",
        "encode_srv-EncodeSrv.EncodeJpeg-CAM2",
        "encode_srv-EncodeSrv.EncodeJpeg-CAM3",
        "encode_srv-EncodeSrv.EncodeJpeg-CAM4",
        "encode_srv-EncodeSrv.EncodeJpeg-CAM5",
        "encode_srv-EncodeSrv.EncodeJpeg-CAM6",
        "encode_srv-EncodeSrv.EncodeJpeg-CAM7",
        "encode_srv-EncodeSrv.EncodeJpeg-CAM8",
        "encode_srv-EncodeSrv.EncodeJpeg-CAM9",
        "encode_srv-EncodeSrv.EncodeJpeg-CAM10",
    };

    for (auto it = global_data::g_topics_mid.begin(); it != global_data::g_topics_mid.end();)
    {
        if ((tmp_video.find(*it) != tmp_video.end()) || (tmp_picture.find(*it)!=tmp_picture.end()))
        {
            it = global_data::g_topics_mid.erase(it);
        }
        else
        {
            it++;
        }
    }
}

void adr_component::pictureTopicInit()
{
    global_data::g_topics_pic.clear();
    global_data::g_topics_pic.push_back("encode_srv-EncodeSrv.EncodeJpeg-CAM0");
    global_data::g_topics_pic.push_back("encode_srv-EncodeSrv.EncodeJpeg-CAM1");
    global_data::g_topics_pic.push_back("encode_srv-EncodeSrv.EncodeJpeg-CAM2");
    global_data::g_topics_pic.push_back("encode_srv-EncodeSrv.EncodeJpeg-CAM3");
    global_data::g_topics_pic.push_back("encode_srv-EncodeSrv.EncodeJpeg-CAM4");
    global_data::g_topics_pic.push_back("encode_srv-EncodeSrv.EncodeJpeg-CAM5");
    global_data::g_topics_pic.push_back("encode_srv-EncodeSrv.EncodeJpeg-CAM6");
    global_data::g_topics_pic.push_back("encode_srv-EncodeSrv.EncodeJpeg-CAM7");
    global_data::g_topics_pic.push_back("encode_srv-EncodeSrv.EncodeJpeg-CAM8");
    global_data::g_topics_pic.push_back("encode_srv-EncodeSrv.EncodeJpeg-CAM9");
    global_data::g_topics_pic.push_back("encode_srv-EncodeSrv.EncodeJpeg-CAM10");
}

void adr_component::rpcTopicInit()
{
    global_data::g_topics_rpc.clear();
    global_data::g_topics_rpc.push_back(PB_BASC_DCENGINEERINGMODEL_RR_SYNCCALIBRATIONFILE_IN);
    global_data::g_topics_rpc.push_back(PB_BASC_DCENGINEERINGMODEL_CNR_STOPTASK_IN);
    //global_data::g_topics_rpc.push_back(PB_BASC_DCFILEUPLOAD_NTF_UPLOADFILE_IN);
    //global_data::g_topics_rpc.push_back(PB_QUERYFILEPATHINFO_GET_QUERYFILEPATHINFO_IN);
    global_data::g_topics_rpc.push_back(PB_BASC_GETFILEDIRRPC_TRANSFILEDIR_IN);
    global_data::g_topics_rpc.push_back(PB_BASC_VIDEORECORDSERVER_RR_INIT_IN);
    global_data::g_topics_rpc.push_back(PB_BASC_VIDEORECORDSERVER_RR_UINIT_IN);
    global_data::g_topics_rpc.push_back(PB_BASC_VIDEORECORDSERVER_RR_REQUESTVIDEOFILE_IN);
    global_data::g_topics_rpc.push_back(PB_BASC_CARFILEUPLOAD_CNR_FILEUPLOAD_C2_IN);
}

void adr_component::calibFileInit()
{
    //get fc_calib
    DIR *fc_dir = opendir(global_data::g_calibration_fc_path.c_str());
    if (NULL == fc_dir)
    {
        Log_Info("opendir fail :{}", global_data::g_calibration_fc_path);
        return;
    }
     struct dirent *dir_info;
    string calibration_fc_onefile;
    std::string absPath = "";
    while ((dir_info = readdir(fc_dir))!=nullptr)
    {
        calibration_fc_onefile = dir_info->d_name;
        
        Log_Info("calibration_fc_onefile: {}", calibration_fc_onefile);

        //if ((calibration_fc_onefile.find("camera_0.json") != std::string::npos) ||(calibration_fc_onefile.find("camera_1.json") != std::string::npos)||(calibration_fc_onefile.find("camera_2.json") != std::string::npos)
        //||(calibration_fc_onefile.find("camera_3.json") != std::string::npos)||(calibration_fc_onefile.find("camera_4.json") != std::string::npos)||(calibration_fc_onefile.find("camera_5.json") != std::string::npos)||(calibration_fc_onefile.find("camera_6.json") != std::string::npos)
        //||(calibration_fc_onefile.find("camera_0.yaml") != std::string::npos) ||(calibration_fc_onefile.find("camera_1.yaml") != std::string::npos)||(calibration_fc_onefile.find("camera_2.yaml") != std::string::npos)
        //||(calibration_fc_onefile.find("camera_3.yaml") != std::string::npos)||(calibration_fc_onefile.find("camera_4.yaml") != std::string::npos)||(calibration_fc_onefile.find("camera_5.yaml") != std::string::npos)||(calibration_fc_onefile.find("camera_6.yaml") != std::string::npos)
        //)
        if((calibration_fc_onefile.find(".yaml")!= std::string::npos))
        {
            absPath = global_data::g_calibration_fc_path + dir_info->d_name;
            string calibration_fc;
            CommonOprSystem::readFileAllOnce(absPath, calibration_fc);
            global_data::g_fc_calib[calibration_fc_onefile]=calibration_fc;
        }

    }
    closedir(fc_dir);
    fc_dir=nullptr;
    dir_info=nullptr;
    //get sc_calib
    DIR *sc_dir = opendir(global_data::g_calibration_sc_path.c_str());
    if (NULL == sc_dir)
    {
        Log_Info("opendir fail :{}", global_data::g_calibration_sc_path);
        return;
    }
    struct dirent *sc_dir_info;
    string calibration_sc_onefile;
    absPath = "";
    while ((sc_dir_info = readdir(sc_dir))!=nullptr)
    {
        calibration_sc_onefile = sc_dir_info->d_name;
        
        Log_Info("calibration_sc_onefile: {}", calibration_sc_onefile);

        //if ((calibration_sc_onefile.find("calpara.json") != std::string::npos) ||(calibration_sc_onefile.find("calpara.txt") != std::string::npos) 
        //||(calibration_sc_onefile.find(".json")!= std::string::npos)||(calibration_sc_onefile.find(".yaml")!= std::string::npos))
        if((calibration_sc_onefile.find(".yaml")!= std::string::npos))
        {
            absPath = global_data::g_calibration_sc_path + sc_dir_info->d_name;
            string calibration_sc;
            CommonOprSystem::readFileAllOnce(absPath, calibration_sc);
            global_data::g_sc_calib[calibration_sc_onefile]=calibration_sc;
        }

    }
    closedir(sc_dir);
    sc_dir=nullptr;
    sc_dir_info=nullptr;
    //get ldr_calib
    DIR *ldr_dir = opendir(global_data::g_calibration_ldr_path.c_str());
    if (NULL == ldr_dir)
    {
        Log_Info("opendir fail :{}", global_data::g_calibration_ldr_path);
        return;
    }
    struct dirent *ldr_dir_info;
    string calibration_ldr_onefile;
    absPath = "";
    while ((ldr_dir_info = readdir(ldr_dir))!=nullptr)
    {
        calibration_ldr_onefile = ldr_dir_info->d_name;
        
        Log_Info("calibration_ldr_onefile: {}", calibration_ldr_onefile);

        if ((calibration_ldr_onefile.find("left_lidar.yaml") != std::string::npos) ||(calibration_ldr_onefile.find("lidar_0.yaml") != std::string::npos)
            ||(calibration_ldr_onefile.find("right_lidar.yaml") != std::string::npos) ||(calibration_ldr_onefile.find("lidar_1.yaml") != std::string::npos)
            ||(calibration_ldr_onefile.find("left_lidar.dat") != std::string::npos) ||(calibration_ldr_onefile.find("right_lidar.dat") != std::string::npos)
            ||(calibration_ldr_onefile.find(".dat")!= std::string::npos)||(calibration_ldr_onefile.find(".yaml")!= std::string::npos))
        {
            absPath = global_data::g_calibration_ldr_path + ldr_dir_info->d_name;
            string calibration_ldr;
            CommonOprSystem::readFileAllOnce(absPath, calibration_ldr);
            global_data::g_ldr_calib[calibration_ldr_onefile]=calibration_ldr;
        }

    }
    closedir(ldr_dir);
    ldr_dir=nullptr;
    ldr_dir_info=nullptr;

    Log_Info("calib size; g_fc_calib:{} g_sc_calib:{} g_ldr_calib:{}", global_data::g_fc_calib.size(), global_data::g_sc_calib.size(), global_data::g_ldr_calib.size());
    return;
}

void adr_component::init()
{
    // 1. 初始化日志器配置：指定日志名称为"adr"，配置文件路径为"./adr/adr.yaml"
    //    作用是加载日志的格式、输出方式、级别等配置
    INIT_LOGGER_NAME_CONFIG("adr","./adr/adr.yaml");
    
    // 2. 根据上述配置创建名为"adr"的日志器实例
    CREATE_LOGGER("adr");
    
    // 3. 为"adr"日志器设置默认的时间戳格式（可能包含在日志输出中）
    SET_DEFAULT_LOGGER_TS("adr");
    
    // 4. 输出初始化日志：记录组件名称和版本号（2025/0819可能是版本日期）
    //    Name()应该是父类CaNode的方法，返回组件名称；adr_VERSION是版本号宏定义
    Log_Info("2025/0819 component: {}  version: {}", Name(), adr_VERSION);
    
    /****** please uncomment the following code as needed ******/
    // 5. 设置缓冲区大小为20（可能是消息处理缓冲区，单位需结合上下文判断）
    SetBufferSize(20);
    
    // 6. 创建一个新线程，执行当前对象的adrInit()方法（组件核心初始化逻辑）
    std::thread main(&adr_component::adrInit, this);
    
    // 7. 注释说明：睡眠1秒是为了保证RPC的BindRequest函数绑定完成
    // 8. 注释说明：修复点：确保capilot相关的所有接口都在adrInit中被调用
    // 9. 线程休眠2秒：等待adrInit中可能的异步初始化（如RPC绑定）完成
    sleep(2);
    
    // 10. 将线程与当前线程分离：允许主线程继续执行，子线程独立运行至结束
    main.detach();
}
void adr_component::shutdown()
{
    isShutDown=true;
    for(int i = 0; i < (int)ThreadType::E_ThreadCount; i++)
    {
         EventLoop::getInstance(static_cast<ThreadType>(i))->m_isRunning = false;
         Log_Info("shutdown i:{}",i);
    }
    for(auto &&c3bThread: global_data::g_c3bThread)
    {
        if(c3bThread.joinable())
        {
            c3bThread.join();
        }
    }
    Log_Info("global_data::g_c3bThread.clear()");
    global_data::g_c3bThread.clear();
}

void adr_component::printLossBatch(const std::string& topic_name,size_t batch) 
{
	static std::map<std::string, size_t> id_map = {
        {ENCODE_SRV_H265_CAM0, 0},
        {ENCODE_SRV_H265_CAM1, 0},
        {ENCODE_SRV_H265_CAM2, 0},
        {ENCODE_SRV_H265_CAM3, 0},
        {ENCODE_SRV_H265_CAM4, 0},
        {ENCODE_SRV_H265_CAM5, 0},
        {ENCODE_SRV_H265_CAM6, 0},
        {ENCODE_SRV_H265_CAM7, 0},
        {ENCODE_SRV_H265_CAM8, 0},
        {ENCODE_SRV_H265_CAM9, 0},
        {ENCODE_SRV_H265_CAM10, 0}
    };

    auto it = id_map.find(topic_name);
    if (it != id_map.end()) 
	{
        if (batch != (it->second + 1)) 
		{
            Log_Info("get data,topic:{} loss frame:{{},{}}", topic_name, it->second, batch);
        }
        it->second = batch;
    }
}

void adr_component::getDataFromCapilot()
{
    std::vector<ProtoData> dataCachVt;
    dataCachVt.reserve(500);
    {
        for (const std::string &topic : global_data::g_topics)
        {

            if(global_data::g_work_status == 2)//只接收泊车状态下的topic
            {
                 if (std::find(global_data::g_parking_topics.begin(), global_data::g_parking_topics.end(), topic) == global_data::g_parking_topics.end())
                 {
                    Log_Info("global_data::g_parking_topics not exist topic: {}",topic);
                    continue ;
                 }
            }

            Log_Info("global_data::g_parking_topics exist topic: {}",topic);
            //Log_Info("get data,topic:{}",topic);
            for(int i=0;i<20;++i)//每个topic就获取20帧数据，防止有发送频率高于10ms的topic，会导致getData一直在获取数据，永远不会返回nullptr进入死循环
            {
                double time=0;
                size_t batch = 0;
                auto data=getData<capilot::RawMessage>(topic,&time,&batch);//返回nullptr表示当前topic数据已经完了
                if(data==nullptr)
                {
                    //Log_Info("data is nullptr");
                    break;
                }
                // if(data->size()==0)
                // {
                //     //Log_Info("data size is 0");
                //     break;
                // }
                Log_Signal("receive topic: {}  data_size: {}", topic, data->size());
                printLossBatch(topic,batch);
                if ((data->size() > 500 * 1024) && (global_data::noLimitBigSet.find(topic) == global_data::noLimitBigSet.end())) // zjs_tmp_  > 500k 并且不是不限制大小的模块的 丢弃
                {
                    if (m_bigTopicSet.find(topic) == m_bigTopicSet.end())//没有
                    {
                        m_bigTopicSet.insert(topic);
                        Log_Info("ERROR: receive data too lager, topic: {}  data_size: {}", topic, data->size());
                    }

                    //Log_Info("ERROR: receive data too lager, topic: {}  data_size: {}", topic, data->size());
                    continue;
                }
                ProtoData pbData;
                pbData.timestamp = time;
                pbData.topic = std::make_shared<std::string>(topic);
                pbData._length = data->size();

                pbData.data = std::make_shared<std::string>((const char*)data->data(), pbData._length);

                std::shared_ptr<std::string> ptr;
                if(!topic.compare("sab-string-top_raw"))//if53接口topic变更
                {
                    ptr=std::make_shared<std::string>((const char*)data->data(), data->size());
                    string LaserPlasmaCloudData=getLaserPlasmaCloudData(topic,*ptr);
                    pbData.data=std::make_shared<std::string>((const char*)LaserPlasmaCloudData.data(), LaserPlasmaCloudData.size());
                    pbData._length = LaserPlasmaCloudData.size();
                }
                pbData.time = getTime();
                // 需要特殊处理的topic;后续拓展放到 specTopiDeal 里
                auto oneIt = specTopiDeal.find(topic);    
                if (oneIt != specTopiDeal.end())
                {
                    oneIt->second(pbData);
                }

                //ADD BY GD
                //获取车辆vin 码
                //static int desensitizeSdkInitCount=0;
                if(global_data::desensitizeSdkInitCount==0)
                {
                    if(!global_data::g_car_vin.empty())
                    {
                        //初始化腾讯加密sdk对应的crt文件
                        if(access("/ds/ca_adas/ca.crt", F_OK)==0)
                        {
                            if(!car_scheduler::Desensitize::getInstance().getHasInitSdk())
                            {
                                if(car_scheduler::globalSdk==nullptr)
                                {
                                    if(global_data::desensitizeSdkInitCount==0)
                                    {
                                        Log_Info("log: g_car_vin :{} g_SdaCaFilePath: {}",global_data::g_car_vin,global_data::g_SdaCaFilePath);
                                        std::thread DesensitizeSdkInit([=](){
                                        car_scheduler::Desensitize::getInstance().Init(global_data::g_car_vin,global_data::g_SdaCaFilePath);
                                        });
                                        DesensitizeSdkInit.detach();
                                    }
                                    global_data::desensitizeSdkInitCount++;
                                }
                            }
                        }
                    }
                }
                
                // 缓存topic数据
                //DataCache::getInstance().addData(std::move(pbData));
                dataCachVt.push_back(std::move(pbData));
            }
        }
    }

    if (dataCachVt.empty()) 
    {
        return;
    }

    DataCache::getInstance().addData(dataCachVt);
    dataCachVt.clear();
    
    return;
}

std::string adr_component::getLaserPlasmaCloudData(const string &topic ,const string &data)
{   
    // Log_Info("gd recv sab-string-right_raw : {} ",topic);
    if (data.size() != sizeof(hb_mem_common_buf_t))
    {
        Log_Info("hbmem topic {} data size err {},expect {}", topic.c_str(), data.size(), sizeof(hb_mem_common_buf_t));
        return "";
    }
    auto common_buf = reinterpret_cast<hb_mem_common_buf_t *>((void *)data.data());
    hb_mem_common_buf_t new_hb_mem;
    {
        std::lock_guard<std::mutex> lg(mutex_);
        if (sharedid_combuf_map_.find(common_buf->share_id) ==
            sharedid_combuf_map_.end())
        {
            // If the shared_id is not found in the map, import the common buffer
            if (hb_mem_import_com_buf(common_buf, &new_hb_mem) != 0)
            {
                Log_Info("hbmem hb_mem_import_com_buf failed, sharedid:{}", common_buf->share_id);
            }
            sharedid_combuf_map_[common_buf->share_id].com_buf = new_hb_mem;
        }
        else
        {
            new_hb_mem = sharedid_combuf_map_[common_buf->share_id].com_buf;
        }
    }
    if (hb_mem_inc_com_buf_consume_cnt(&new_hb_mem) != 0)
    {
        Log_Info("hbmem topic {} consume err! id:{}",  topic.c_str(), new_hb_mem.share_id);
        return "";
    }
    std::string laserPlasmaCloudData((char *)new_hb_mem.virt_addr, new_hb_mem.size);
    if (hb_mem_dec_consume_cnt(new_hb_mem.fd) != 0)
    {
        Log_Info("hbmem hb_mem_dec_consume_cnt failed, sharedid:{}", new_hb_mem.share_id);
            return "";
    }
    return laserPlasmaCloudData;
}

#if 0
void adr_component::onObjectCallback(const std::string &topic, const capilot::RawMessage &data, const double &time) // 后续用这个 const capilot::RawMessage &data /const std::string &data
{
    Log_Signal("receive topic: {}  data_size: {}", topic, data.size());

    if (global_data::blackTopicSet.find(topic) != global_data::blackTopicSet.end())//黑名单中的topic不采集
    {
        return;
    }    

    if ((data.size() > 500 * 1024) && (global_data::noLimitBigSet.find(topic) == global_data::noLimitBigSet.end())) // zjs_tmp_  > 500k 并且不是不限制大小的模块的 丢弃
    {
        Log_Info("ERROR: receive data too lager, topic: {}  data_size: {}", topic, data.size());
        return;
    }

    // if (data.size() == 0)//泊车远程控制 ad_apaabnormexitreas 那帧发的data_size 为0；先不过滤这种
    // {
    //     return;
    // }  

    // 拷贝数据备份，以免共享内存释放
    if(topic.find("encode_srv-EncodeSrv.EncodeH265-CAM")!=std::string::npos)
    {
        Log_Info("receive topic:{},time:{}",topic,time);
    }
    ProtoData pbData;
    pbData.timestamp = time;
    pbData.topic = std::make_shared<std::string>(topic);
    pbData._length = data.size();

    pbData.data = std::make_shared<std::string>((const char*)data.data(), pbData._length);
    
    pbData.time = getTime();
    
    // 拦截做视频脱敏接收
    if (AntianaphylaxisQueue::getInstance().receiveDesensData(pbData))
    {
        return;
    }

    // 需要特殊处理的topic;后续拓展放到 specTopiDeal 里
    auto oneIt = specTopiDeal.find(topic);    
    if (oneIt != specTopiDeal.end())
    {
        oneIt->second(pbData);
    }

    // 缓存topic数据
    DataCache::getInstance().addData(pbData);
}
#endif
// 定义adr_component类的RPC回调函数，用于处理接收到的RPC请求
// 参数：topic（RPC话题名）、requestData（请求数据）、replyData（回复数据，输出参数）
void adr_component::onObjectRpcCallback(const std::string &topic, const std::string &requestData, std::string *replyData)
{
    // 记录接收到的RPC话题日志，便于调试和跟踪
    Log_Topic("receive Rpc topic: {}", topic);

    // 处理"同步标定文件"类型的RPC请求
    if (PB_BASC_DCENGINEERINGMODEL_RR_SYNCCALIBRATIONFILE_IN == topic)
    {
        // 调用SoaEnginerringModel单例的RR_SyncCalibrationFile方法处理请求
        SoaEnginerringModel::getInstance().RR_SyncCalibrationFile(topic, requestData, *replyData);
    }

    // 处理"停止工程模型任务"类型的RPC请求
    if (PB_BASC_DCENGINEERINGMODEL_CNR_STOPTASK_IN == topic)
    {
        // 调用SoaEnginerringModel单例的Cnr_StopTask方法处理请求
        SoaEnginerringModel::getInstance().Cnr_StopTask(topic, requestData, *replyData);
        return; // 处理完毕后返回，避免执行后续逻辑
    }

    // 以下为注释掉的代码，可能是暂不启用的功能：处理"文件上传通知"请求
    // if (PB_BASC_DCFILEUPLOAD_NTF_UPLOADFILE_IN == topic)
    // {
    //     SoaUploadFileServer::getInstance().Ntf_UploadFile(topic, requestData, *replyData);
    //     return;
    // }

    // 以下为注释掉的代码，可能是暂不启用的功能：处理"查询文件路径信息"请求
    // if (PB_QUERYFILEPATHINFO_GET_QUERYFILEPATHINFO_IN == topic)
    // {
    //     SoaQueryFilePathInfo::getInstance().Get_QueryFilePathInfo(topic, requestData, *replyData);
    //     return;
    // }

    // 处理"传输文件目录"类型的RPC请求
    if (PB_BASC_GETFILEDIRRPC_TRANSFILEDIR_IN == topic)
    {
        // 调用SoaGetFileDirRpc单例的transFileDir方法处理请求
        SoaGetFileDirRpc::getInstance().transFileDir(topic, requestData, *replyData);
        return; // 处理完毕后返回
    }

    if (PB_BASC_VIDEORECORDSERVER_RR_INIT_IN == topic)//哨塔初始化
    {
        // 调用SoaVideoRecordServer单例的RR_Init方法处理请求
        SoaVideoRecordServer::getInstance().RR_Init(topic, requestData, *replyData);
    }

    if (PB_BASC_VIDEORECORDSERVER_RR_UINIT_IN == topic)
    {
        // 调用SoaVideoRecordServer单例的RR_Uinit方法处理请求
        SoaVideoRecordServer::getInstance().RR_Uinit(topic, requestData, *replyData);
        return; // 处理完毕后返回
    }

    // 处理"请求视频文件"类型的RPC请求-座舱发送过来的视频请求
    if (PB_BASC_VIDEORECORDSERVER_RR_REQUESTVIDEOFILE_IN == topic)
    {
        // 调用SoaVideoRecordServer单例的RR_RequestVideoFile方法处理请求
        SoaVideoRecordServer::getInstance().RR_RequestVideoFile(topic, requestData, *replyData);
        return; // 处理完毕后返回
    }

    // 处理"C2文件上传"类型的RPC请求
    if (PB_BASC_CARFILEUPLOAD_CNR_FILEUPLOAD_C2_IN == topic)
    {
        // 调用SoaCarFileUpload单例的Cnr_FileUpload_C2方法处理请求
        SoaCarFileUpload::getInstance().Cnr_FileUpload_C2(topic, requestData, *replyData);
        return; // 处理完毕后返回
    }
}


void adr_component::selfGetAndrEnvir()
{
    Soa::PB_Basc_AndroidEnvironment_Get_Environment_In request;
    Soa::PB_Basc_AndroidEnvironment_Get_Environment_Out reply;

    int ret, env;
    for(uint32_t i = 0; i < 10; i++)
    {
        // 0:成功,1:超时,2:请求服务未绑定,-1:未知错误
        ret = Request(PB_BASC_ANDROIDENVIRONMENT_GET_ENVIRONMENT_IN, request, &reply,100);//设置100ms超时
        if (ret != 0)
        {
            Log_Info("selfGetAndrEnvir get reply ret:{}", ret);
            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
            continue;
        }
        else
        {
            env = reply.return_();
        }
        break;
    }

    Log_Info("selfGetAndrEnvir get reply ret:{}", ret);
    if(ret == 0)
    {
        Log_Info("selfGetAndrEnvir success; env:{}", env);

        //0：预生产环境 1：正式环境
        if (env == 0)
        {
            global_data::g_cloudNetPrefix = STR_PREEVN;
        }
        else
        {
            global_data::g_cloudNetPrefix = STR_DEVEVN;
        }
    }

    Log_Info("selfGetAndrEnvir global_data::g_cloudNetPrefix:{}", global_data::g_cloudNetPrefix);
    return;
}
void adr_component::getAndrEnvirAgain()
{
    Soa::PB_Basc_AndroidEnvironment_Get_Environment_In request;
    Soa::PB_Basc_AndroidEnvironment_Get_Environment_Out reply;

    int ret, env;

    // 0:成功,1:超时,2:请求服务未绑定,-1:未知错误
    ret = Request(PB_BASC_ANDROIDENVIRONMENT_GET_ENVIRONMENT_IN, request, &reply,100);//设置100ms超时
    if (ret != 0)
    {
        Log_Info("getAndrEnvirAgain get reply ret:{}", ret);
        return;
    }
    else
    {
        env = reply.return_();
    }

    // Log_Info("getAndrEnvirAgain get reply ret:{}", ret);
    if (ret == 0)
    {
        Log_Info("getAndrEnvirAgain success; env:{}", env);

        // 0：预生产环境 1：正式环境
        string tmpPre;
        if (env == 0)
        {
            tmpPre = STR_PREEVN;
        }
        else
        {
            tmpPre = STR_DEVEVN;
        }

        if (global_data::g_cloudNetPrefix.compare(tmpPre))//变化了才打印
        {
            Log_Info("getAndrEnvirAgain global_data::g_cloudNetPrefix:{}", global_data::g_cloudNetPrefix);
        }
        
        global_data::g_cloudNetPrefix = tmpPre;
    }

    return;
}